﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace MineFlagger
{
    public partial class SmileButton : Control
    {
        Image smilesBMP;              // array of smile images

        Bitmap upButtonBMP;           // up/doube blank button graphics
        Bitmap downButtonBMP;

        const int buttonWidth = 26;   // constants describing size of button and smile images
        const int buttonHeight = 26;
        const int smileHeight = 17;   
        const int smileWidth = 17;

        bool mouseDown;               // flags to keep track of mouse down, mouse over
        bool mouseOver;               // valid only when mouseDown

        public SmileButton()
        {   
            InitializeComponent();

            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.DoubleBuffer, true);

            // load/draw offscreen bitmaps for bliting 
            loadSmilesBMP();
            drawDownButtonBMP();
            drawUpButtonBMP();

            Width = buttonWidth;
            Height = buttonHeight;
        }

        #region Public Properties: SmileType

        SmileType _smileType;
        public SmileType SmileType
        {
            get { return _smileType; }
            set
            {
                if (_smileType == value)
                    return;

                _smileType = value;
                Invalidate();
            }
        }

        #endregion

        #region Mouse Tracking

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);

            if (e.Button == MouseButtons.Left)
            {
                mouseDown = true;
                mouseOver = true;
                Invalidate();
            }
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);

            if (e.Button == MouseButtons.Left)
            {
                mouseDown = false;

                if (mouseOver)
                {
                    // note: we would generate a click here, but the funcitonalty is baked into Control, our base class 
                    Invalidate();
                }
            }
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (!mouseDown) return;
            
            // check if we have moved out of bounds to in bounds or vice versa;
            // if so, update visual
            bool inBounds = ClientRectangle.Contains(e.X, e.Y);
            
            if (inBounds != mouseOver) 
            {
                mouseOver = !mouseOver;
                Invalidate();
            }

        }

        #endregion

        #region Drawing

        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);

            if (mouseDown && mouseOver) 
            {
                // draw down button (butten pressed)
                pe.Graphics.DrawImage(downButtonBMP, 0, 0);
                pe.Graphics.DrawImage(smilesBMP, 6, 6, new Rectangle((int)SmileType.Happy * smileWidth, 0, smileWidth, smileHeight), GraphicsUnit.Pixel);

            }
            else 
            {
                // draw up button (not pressed)
                pe.Graphics.DrawImage(upButtonBMP, 0, 0);
                pe.Graphics.DrawImage(smilesBMP, 5, 5, new Rectangle((int)SmileType * smileWidth, 0, smileWidth, smileHeight), GraphicsUnit.Pixel);

            }
        }
        
        void loadSmilesBMP()
        {
            if (smilesBMP != null) return;

            System.Reflection.Assembly thisExe;
            thisExe = System.Reflection.Assembly.GetExecutingAssembly();
            System.IO.Stream file = thisExe.GetManifestResourceStream("MineFlagger.smiles.png");
            
            smilesBMP = Image.FromStream(file);
            
            file.Close();
        }
                
        void drawUpButtonBMP()
        {
            if (upButtonBMP != null) return;
            upButtonBMP = new Bitmap(buttonWidth, buttonHeight);
            Graphics g = Graphics.FromImage(upButtonBMP);

            Brush darkBorder = Brushes.DarkGray;
            Brush lightBorder = Brushes.White;

            int x, y, width, height;

            // TOP border
            x = 0; y = 0; width = buttonWidth - 1;
            g.FillRectangle(darkBorder, x, y, width, 1); x++; y++; width -= 2;
            g.FillRectangle(lightBorder, x, y, width, 1); x++; y++; width -= 2;
            g.FillRectangle(lightBorder, x, y, width, 1);

            // LEFT border
            x = 0; y = 0; height = buttonHeight - 1;
            g.FillRectangle(darkBorder, x, y, 1, height); x++; y++; height -= 2;
            g.FillRectangle(lightBorder, x, y, 1, height); x++; y++; height -= 2;
            g.FillRectangle(lightBorder, x, y, 1, height);

            // RIGHT border
            x = buttonWidth - 3; y = 3; height = buttonHeight - 6;
            g.FillRectangle(darkBorder, x, y, 1, height); x++; y--; height += 1;
            g.FillRectangle(darkBorder, x, y, 1, height); x++; y--; height += 1;
            g.FillRectangle(darkBorder, x, y, 1, height);

            // BOTTOM border
            x = 3; y = buttonHeight - 3; width = buttonWidth - 3;
            g.FillRectangle(darkBorder, x, y, width, 1); x--; y++; width += 1;
            g.FillRectangle(darkBorder, x, y, width, 1); x--; y++; width += 1;
            g.FillRectangle(darkBorder, x, y, width, 1);

            g.Dispose();

        }
                
        void drawDownButtonBMP()
        {

            if (downButtonBMP != null) return;
            downButtonBMP = new Bitmap(buttonWidth, buttonHeight);
            Graphics g = Graphics.FromImage(downButtonBMP);

            Brush darkBorder = Brushes.DarkGray;
            Brush lightBorder = Brushes.White;

            int x, y, width, height;

            // TOP border
            x = 0; y = 0; width = buttonWidth - 1;
            g.FillRectangle(darkBorder, x, y, width, 2);

            // LEFT border
            x = 0; y = 0; height = buttonHeight - 1;
            g.FillRectangle(darkBorder, x, y, 2, height);

            // RIGHT border
            x = buttonWidth - 1; y = 1; height = buttonHeight - 1;
            g.FillRectangle(darkBorder, x, y, 1, height);

            // BOTTOM border
            x = 1; y = buttonHeight - 1; width = buttonWidth - 1;
            g.FillRectangle(darkBorder, x, y, width, 1); 


            g.Dispose();
        }

        #endregion


    }

    public enum SmileType { Happy = 0, Worried, Cool, Sad }
}
